package com.geek.water.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geek.water.constant.BillingConstants;
import com.geek.water.entity.*;
import com.geek.water.entity.Bill;
import com.geek.water.entity.BillDetail;
import com.geek.water.entity.Customer;
import com.geek.water.entity.Device;
import com.geek.water.exception.WaterException;
import com.geek.water.mapper.BillMapper;
import com.geek.water.service.*;
import com.geek.water.utils.BillCodeGenerator;
import com.geek.water.mapper.DeviceDataMapper;
import com.geek.water.vo.BillQueryVO;
import com.geek.water.vo.BillVO;
import com.geek.water.vo.BillDetailVO;
import com.geek.water.vo.CustomerVO;
import com.geek.water.vo.PageQueryVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class BillServiceImpl extends ServiceImpl<BillMapper, Bill> implements BillService {

    @Autowired
    private PaymentRecordService paymentRecordService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private AreaService areaService;

    @Autowired
    private SiteService siteService;

    @Autowired
    private BillDetailService billDetailService;

    @Autowired
    private GlobalWaterPriceTierService globalWaterPriceTierService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private DeviceDataMapper deviceDataMapper;

    @Override
    public Page<BillVO> listBills(PageQueryVO queryVO, BillQueryVO billQueryVO) {
        try {
            Page<Bill> page = Page.of(
                    queryVO.getCurrentPage() != null ? queryVO.getCurrentPage() : 1,
                    queryVO.getPageSize() != null ? queryVO.getPageSize() : 10
            );

            LambdaQueryWrapper<Bill> wrapper = new LambdaQueryWrapper<>();

            // 客户ID过滤
            if (billQueryVO.getCustomerId() != null) {
                wrapper.eq(Bill::getCustomerId, billQueryVO.getCustomerId());
            }

            // 账单状态过滤
            if (billQueryVO.getStatus() != null && !billQueryVO.getStatus().isEmpty()) {
                wrapper.in(Bill::getStatus, billQueryVO.getStatus());
            }

            // 时间段过滤 - 使用创建时间作为过滤条件
            if (billQueryVO.getStartDate() != null) {
                wrapper.ge(Bill::getCreatedAt, billQueryVO.getStartDate().atStartOfDay());
            }
            if (billQueryVO.getEndDate() != null) {
                wrapper.le(Bill::getCreatedAt, billQueryVO.getEndDate().atTime(23, 59, 59));
            }

            wrapper.orderByDesc(Bill::getCreatedAt);

            Page<Bill> billPage = baseMapper.selectPage(page, wrapper);
            return convertToBillVOPage(billPage);
        } catch (Exception e) {
            log.error("查询账单列表失败", e);
            throw new WaterException("系统内部错误，请稍后重试");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BillVO createBill(BillVO billVO) throws WaterException {
        // 校验必填字段 - 移除对periodStart和periodEnd的校验
        if (billVO.getCustomerId() == null) {
            throw new WaterException(BillingConstants.PARAM_INVALID);
        }

        // 实体拷贝
        Bill bill = new Bill();
        BeanUtils.copyProperties(billVO, bill);

        // 生成唯一的账单编号
        String billCode = generateUniqueBillCode();
        bill.setBillCode(billCode);

        // 设置默认的开票状态为未开票
        bill.setInvoiced(0);

        try {
            // 保存主表
            baseMapper.insert(bill);
        } catch (Exception e) {
            // 如果是唯一约束冲突，重新生成bill_code
            if (e.getMessage().contains("uk_bill_code") || e.getMessage().contains("Duplicate entry")) {
                log.warn("账单编号冲突，重新生成: {}", billCode);
                billCode = generateUniqueBillCode();
                bill.setBillCode(billCode);
                baseMapper.insert(bill);
            } else {
                throw e;
            }
        }

        // 返回带 ID 的 VO
        BillVO result = new BillVO();
        BeanUtils.copyProperties(bill, result);
        return result;
    }

    /**
     * 生成唯一的账单编号
     * @return 唯一的账单编号
     */
    private String generateUniqueBillCode() throws WaterException {
        String billCode;
        int maxAttempts = 20; // 最大尝试次数
        int attempts = 0;

        do {
            try {
                billCode = BillCodeGenerator.generateBillCode();
                if (billCode == null || billCode.trim().isEmpty()) {
                    throw new WaterException("生成的账单编号为空");
                }

                // 检查数据库中是否已存在相同的bill_code
                Bill existingBill = findByBillCode(billCode);
                if (existingBill == null) {
                    return billCode; // 找到唯一的bill_code
                }
                attempts++;
                if (attempts >= maxAttempts) {
                    throw new WaterException("无法生成唯一的账单编号，请稍后重试");
                }
                // 短暂延迟，避免CPU占用过高
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new WaterException("生成账单编号被中断");
                }
            } catch (Exception e) {
                log.error("生成账单编号失败: {}", e.getMessage(), e);
                throw new WaterException("生成账单编号失败: " + e.getMessage());
            }
        } while (true);
    }

    @Override
    public boolean deleteBillWithCheck(Long billId) {
        // 1. 查询账单信息
        Bill bill = baseMapper.selectById(billId);
        if (bill == null) {
            throw new WaterException("账单不存在");
        }

        // 2. 检查账单是否已完成（状态为已支付）
        if (!"paid".equals(bill.getStatus())) {
            return false;
        }

        // 3. 检查是否已超过两年（从支付完成时间开始计算）
        LocalDateTime paidTime = bill.getPaidTime();
        if (paidTime == null) {
            return false;
        }

        // 计算当前时间与支付时间的差值
        LocalDateTime twoYearsAgo = LocalDateTime.now().minusYears(2);
        if (paidTime.isBefore(twoYearsAgo)) {
            // 超过两年，执行删除
            baseMapper.deleteById(billId);
            return true;
        }

        return false;
    }

    @Override
    public void updateBillStatus(Long billId, String status) {
        // 1. 校验账单是否存在
        Bill bill = baseMapper.selectById(billId);
        if (bill == null) {
            throw new WaterException("账单不存在");
        }

        // 2. 处理不同状态的业务逻辑
        switch (status) {
            case "paid":
                // 支付状态更新，记录支付时间
                bill.setStatus("paid");
                bill.setPaidTime(LocalDateTime.now());  // 设置当前时间为支付时间
                break;
            case "overdue":
                // 逾期状态更新
                bill.setStatus("overdue");
                break;
            case "refunded":
                // 退款状态更新
                bill.setStatus("refunded");
                break;
            case "unpaid":
                // 未支付状态，清除支付时间记录
                bill.setStatus("unpaid");
                bill.setPaidTime(null);  // 清除支付时间
                break;
            default:
                throw new WaterException("不支持的账单状态");
        }

        // 3. 更新最后操作时间
        bill.setUpdatedAt(LocalDateTime.now());

        // 4. 保存更新
        baseMapper.updateById(bill);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Bill generateBillFromDeviceReadings(Long customerId, String billingPeriod) throws WaterException {
        try {
            log.error("=== 开始生成账单 - 客户ID: {}, 计费周期: {} ===", customerId, billingPeriod);

            // 0. 检查是否已经为该客户和计费周期生成过账单
            if (existsBillByCustomerAndPeriod(customerId, billingPeriod)) {
                log.error("=== 客户 {} 在计费周期 {} 已经存在账单，不允许重复生成 ===", customerId, billingPeriod);
                throw new WaterException("该客户在指定计费周期已经存在账单，不允许重复生成");
            }

            // 1. 获取客户的所有设备计费信息
            List<BillDetail> deviceBillingList = getCustomerDeviceBilling(customerId, billingPeriod);

            if (deviceBillingList.isEmpty()) {
                log.error("=== 该客户在指定周期内没有可计费的设备数据 ===");
                throw new WaterException("该客户在指定周期内没有可计费的设备数据");
            }

            log.error("=== 获取到 {} 个设备的计费信息 ===", deviceBillingList.size());

            // 打印每个设备的计费详情
            for (BillDetail detail : deviceBillingList) {
                log.error("=== 设备 {} 计费详情 - 用水量: {}, 小计: {} ===",
                        detail.getDeviceId(), detail.getUsageAmount(), detail.getSubtotal());
            }

            // 2. 计算总金额
            BigDecimal totalAmount = deviceBillingList.stream()
                    .map(BillDetail::getSubtotal)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            log.error("=== 账单总金额: {} ===", totalAmount);

            // 3. 创建账单
            Bill bill = new Bill();
            bill.setCustomerId(customerId);
            bill.setBillingPeriod(billingPeriod); // 设置计费周期
            bill.setAmount(totalAmount);
            bill.setStatus("unpaid");
            bill.setInvoiced(0);
            bill.setBillCode(generateUniqueBillCode());

            log.error("=== 创建账单: {} ===", bill.getBillCode());

            // 4. 保存账单
            this.save(bill);

            // 5. 保存账单明细
            for (BillDetail detail : deviceBillingList) {
                detail.setBillId(bill.getId());
                billDetailService.save(detail);
                log.error("=== 保存账单明细 - 设备ID: {}, 账单ID: {} ===", detail.getDeviceId(), bill.getId());
            }

            log.error("=== 保存了 {} 条账单明细 ===", deviceBillingList.size());

            // 6. 更新设备的抄表读数
            updateDeviceReadings(deviceBillingList);

            log.error("=== 账单生成成功 - 账单ID: {}, 账单编号: {}, 包含 {} 个设备 ===",
                    bill.getId(), bill.getBillCode(), deviceBillingList.size());
            return bill;
        } catch (Exception e) {
            log.error("生成账单失败 - 客户ID: {}, 计费周期: {}, 错误: {}", customerId, billingPeriod, e.getMessage(), e);
            throw new WaterException("生成账单失败: " + e.getMessage());
        }
    }

    @Override
    public BillDetail calculateDeviceUsage(Long deviceId, String billingPeriod) throws WaterException {
        try {
            log.info("开始计算设备用水量 - 设备ID: {}, 计费周期: {}", deviceId, billingPeriod);

            // 1. 获取设备信息
            Device device = deviceService.getById(deviceId);
            if (device == null) {
                throw new WaterException("设备不存在");
            }

            // 2. 获取区域信息（用于获取水费单价）
            Area area = areaService.getById(device.getAreaId());
            if (area == null) {
                throw new WaterException("设备所属区域不存在");
            }

            // 3. 获取站点信息
            Site site = siteService.getById(area.getSiteId());
            if (site == null) {
                throw new WaterException("区域所属站点不存在");
            }

            // 4. 计算用水量
            BigDecimal currentReading = device.getCurrentReading();
            // 从device_data表获取上次读数
            BigDecimal lastReading = getLastReadingFromDeviceData(deviceId, billingPeriod);

            log.info("设备 {} 的当前读数: {}, 上次读数: {}", deviceId, currentReading, lastReading);

            if (currentReading == null || lastReading == null) {
                throw new WaterException("设备抄表数据不完整，当前读数: " + currentReading + ", 上次读数: " + lastReading);
            }

            BigDecimal usageAmount = currentReading.subtract(lastReading);
            if (usageAmount.compareTo(BigDecimal.ZERO) < 0) {
                throw new WaterException("当前读数不能小于上次读数");
            }

            // 5. 计算费用（使用阶梯水费）
            BigDecimal subtotal;

            if (usageAmount.compareTo(BigDecimal.ZERO) == 0) {
                // 用水量为0时，收取最小计费金额
                subtotal = BillingConstants.MIN_BILLING_AMOUNT;
                log.info("设备 {} 用水量为0，按最小计费金额收取: {}", deviceId, subtotal);
            } else if (usageAmount.compareTo(BillingConstants.MIN_BILLING_UNIT) < 0) {
                // 用水量小于最小计费单位时，按最小计费单位计费（使用默认阶梯水费）
                subtotal = globalWaterPriceTierService.calculateGlobalTieredPrice(BillingConstants.MIN_BILLING_UNIT);
                log.info("设备 {} 用水量 {} 小于最小计费单位 {}，按最小计费单位计费: {}",
                        deviceId, usageAmount, BillingConstants.MIN_BILLING_UNIT, subtotal);
            } else {
                // 使用全局阶梯水费计算
                subtotal = globalWaterPriceTierService.calculateGlobalTieredPrice(usageAmount);
                log.info("设备 {} 用水量: {}, 全局阶梯计费结果: {}", deviceId, usageAmount, subtotal);
            }

            // 6. 创建账单明细
            BillDetail detail = new BillDetail();
            detail.setDeviceId(deviceId);
            detail.setAreaId(device.getAreaId());
            detail.setSiteId(area.getSiteId());
            detail.setUsageAmount(usageAmount);
            detail.setSubtotal(subtotal);
            detail.setBillingPeriod(billingPeriod);
            detail.setCurrentReading(currentReading);
            detail.setLastReading(lastReading);


            return detail;
        } catch (Exception e) {
            log.error("计算设备 {} 用水量失败: {}", deviceId, e.getMessage(), e);
            throw new WaterException("计算设备用水量失败: " + e.getMessage());
        }
    }

    @Override
    public List<BillDetail> getCustomerDeviceBilling(Long customerId, String billingPeriod) {
        try {
            log.error("=== 开始获取客户设备计费信息 - 客户ID: {}, 计费周期: {} ===", customerId, billingPeriod);

            // 1. 获取客户的所有站点
            List<Site> sites = siteService.lambdaQuery()
                    .eq(Site::getCustomerId, customerId)
                    .list();

            if (sites.isEmpty()) {
                log.error("=== 客户 {} 没有关联的站点 ===", customerId);
                return Collections.emptyList();
            }

            List<Long> siteIds = sites.stream().map(Site::getId).collect(Collectors.toList());
            log.error("=== 客户 {} 的站点ID: {} ===", customerId, siteIds);

            // 2. 获取站点下的所有区域
            List<Area> areas = areaService.lambdaQuery()
                    .in(Area::getSiteId, siteIds)
                    .list();

            if (areas.isEmpty()) {
                log.error("=== 客户 {} 的站点下没有区域 ===", customerId);
                return Collections.emptyList();
            }

            List<Long> areaIds = areas.stream().map(Area::getId).collect(Collectors.toList());
            log.error("=== 客户 {} 的区域ID: {} ===", customerId, areaIds);

            // 3. 获取区域下的所有设备
            List<Device> devices = deviceService.lambdaQuery()
                    .in(Device::getAreaId, areaIds)
                    .list();

            if (devices.isEmpty()) {
                log.error("=== 客户 {} 的区域下没有设备 ===", customerId);
                return Collections.emptyList();
            }

            log.error("=== 客户 {} 找到 {} 个设备 ===", customerId, devices.size());

            // 打印每个设备的详细信息
            for (Device device : devices) {
                log.error("=== 设备ID: {}, 序列号: {}, 区域ID: {}, 当前读数: {} ===",
                        device.getId(), device.getSerialNo(), device.getAreaId(),
                        device.getCurrentReading());
            }

            // 4. 计算每个设备的计费信息
            List<BillDetail> billingDetails = new ArrayList<>();
            int successCount = 0;
            int failCount = 0;

            for (Device device : devices) {
                try {
                    log.error("=== 开始计算设备 {} 的计费信息 ===", device.getId());

                    // 计费周期由业务逻辑处理，设备不再存储计费周期
                    log.error("=== 设备 {} 开始计算计费信息，计费周期: {} ===", device.getId(), billingPeriod);

                    BillDetail detail = calculateDeviceUsage(device.getId(), billingPeriod);
                    billingDetails.add(detail);
                    successCount++;
                    log.error("=== 设备 {} 计费信息计算成功，用水量: {}, 费用: {} ===",
                            device.getId(), detail.getUsageAmount(), detail.getSubtotal());
                } catch (Exception e) {
                    failCount++;
                    log.error("=== 计算设备 {} 计费信息失败: {} ===", device.getId(), e.getMessage());
                }
            }

            log.error("=== 客户 {} 计费计算完成 - 成功: {} 个设备, 失败: {} 个设备, 总计: {} 个设备 ===",
                    customerId, successCount, failCount, billingDetails.size());
            return billingDetails;
        } catch (Exception e) {
            log.error("获取客户设备计费信息失败", e);
            return Collections.emptyList();
        }
    }

    /**
     * 更新设备的抄表读数
     */
    private void updateDeviceReadings(List<BillDetail> billingDetails) {
        for (BillDetail detail : billingDetails) {
            try {
                Device device = deviceService.getById(detail.getDeviceId());
                if (device != null) {
                    // 更新设备当前读数，历史读数保存在device_data表中
                    device.setCurrentReading(detail.getCurrentReading());
                    deviceService.updateById(device);
                }
            } catch (Exception e) {
                log.error("更新设备 {} 抄表读数失败", detail.getDeviceId(), e);
            }
        }
    }

    private Page<BillVO> convertToBillVOPage(Page<Bill> billPage) {
        Page<BillVO> voPage = new Page<>();
        voPage.setCurrent(billPage.getCurrent());
        voPage.setSize(billPage.getSize());
        voPage.setTotal(billPage.getTotal());
        voPage.setPages(billPage.getPages());

        // 获取客户信息
        List<Long> customerIds = billPage.getRecords().stream()
                .map(Bill::getCustomerId)
                .filter(id -> id != null) // 过滤掉null值
                .distinct()
                .collect(Collectors.toList());

        Map<Long, CustomerVO> customerMap;
        try {
            // 安全获取客户信息
            if (!customerIds.isEmpty()) {
                List<CustomerVO> customers = baseMapper.getCustomerInfoByIds(customerIds);
                customerMap = customers.stream()
                        .collect(Collectors.toMap(CustomerVO::getId, c -> c, (existing, replacement) -> existing));
            } else {
                customerMap = Collections.emptyMap();
            }
        } catch (Exception e) {
            log.error("获取客户信息失败: {}", e.getMessage());
            customerMap = Collections.emptyMap();
        }

        Map<Long, CustomerVO> finalCustomerMap = customerMap;
        List<BillVO> voList = billPage.getRecords().stream().map(bill -> {
            BillVO vo = new BillVO();
            BeanUtils.copyProperties(bill, vo);  // 使用BeanUtils复制所有属性，包括paidTime

            // 安全设置客户名称
            CustomerVO customer = finalCustomerMap.get(bill.getCustomerId());
            vo.setCustomerName(customer != null ? customer.getName() : "未知客户");

            return vo;
        }).collect(Collectors.toList());

        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public Bill findByBillCode(String billCode) {
        return baseMapper.getBillByBillCode(billCode);
    }

    @Override
    public boolean existsBillByCustomerAndPeriod(Long customerId, String billingPeriod) {
        return this.lambdaQuery()
                .eq(Bill::getCustomerId, customerId)
                .eq(Bill::getBillingPeriod, billingPeriod)
                .exists();
    }

    @Override
    public boolean deleteBillManually(Long billId) throws WaterException {
        // 1. 查询账单信息
        Bill bill = baseMapper.selectById(billId);
        if (bill == null) {
            throw new WaterException("账单不存在");
        }

        // 2. 检查账单状态，只允许删除未支付的账单
        if ("paid".equals(bill.getStatus())) {
            throw new WaterException("已支付的账单不能删除，请先标记为未支付");
        }

        // 3. 删除账单明细
        try {
            billDetailService.lambdaUpdate()
                    .eq(BillDetail::getBillId, billId)
                    .remove();
        } catch (Exception e) {
            log.error("删除账单明细失败，账单ID: {}", billId, e);
            throw new WaterException("删除账单明细失败: " + e.getMessage());
        }

        // 4. 删除主账单
        try {
            baseMapper.deleteById(billId);
            log.info("手动删除账单成功，账单ID: {}, 账单编号: {}", billId, bill.getBillCode());
            return true;
        } catch (Exception e) {
            log.error("删除账单失败，账单ID: {}", billId, e);
            throw new WaterException("删除账单失败: " + e.getMessage());
        }
    }

    @Override
    public boolean deleteBillsBatch(List<Long> billIds) throws WaterException {
        if (billIds == null || billIds.isEmpty()) {
            throw new WaterException("账单ID列表不能为空");
        }

        // 1. 检查所有账单是否存在且状态是否允许删除
        List<Bill> bills = baseMapper.selectBatchIds(billIds);
        if (bills.size() != billIds.size()) {
            throw new WaterException("部分账单不存在");
        }

        // 2. 检查账单状态
        for (Bill bill : bills) {
            if ("paid".equals(bill.getStatus())) {
                throw new WaterException("账单 " + bill.getBillCode() + " 已支付，不能删除，请先标记为未支付");
            }
        }

        // 3. 删除账单明细
        try {
            billDetailService.lambdaUpdate()
                    .in(BillDetail::getBillId, billIds)
                    .remove();
        } catch (Exception e) {
            log.error("批量删除账单明细失败，账单ID: {}", billIds, e);
            throw new WaterException("批量删除账单明细失败: " + e.getMessage());
        }

        // 4. 删除主账单
        try {
            baseMapper.deleteBatchIds(billIds);
            log.info("批量删除账单成功，账单ID: {}", billIds);
            return true;
        } catch (Exception e) {
            log.error("批量删除账单失败，账单ID: {}", billIds, e);
            throw new WaterException("批量删除账单失败: " + e.getMessage());
        }
    }

    @Override
    public BillDetailVO getBillDetailById(Long billId) {
        try {
            // 1. 查询账单基本信息
            Bill bill = baseMapper.selectById(billId);
            if (bill == null) {
                return null;
            }

            // 2. 查询客户信息
            Customer customer = customerService.getById(bill.getCustomerId());

            // 3. 查询账单明细
            List<BillDetail> billDetails = billDetailService.getDetailsByBillId(billId);

            // 4. 查询关联设备信息
            List<Device> devices = new ArrayList<>();
            if (billDetails != null && !billDetails.isEmpty()) {
                List<Long> deviceIds = billDetails.stream()
                        .map(BillDetail::getDeviceId)
                        .filter(Objects::nonNull)
                        .distinct()
                        .collect(Collectors.toList());

                if (!deviceIds.isEmpty()) {
                    devices = deviceService.listByIds(deviceIds);
                }
            }

            // 5. 计算总用水量
            BigDecimal totalUsageAmount = BigDecimal.ZERO;
            if (billDetails != null) {
                totalUsageAmount = billDetails.stream()
                        .map(BillDetail::getUsageAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
            }

            // 6. 构建BillDetailVO
            BillDetailVO detailVO = new BillDetailVO();
            BeanUtils.copyProperties(bill, detailVO);

            detailVO.setCustomer(customer);
            detailVO.setBillDetails(billDetails);
            detailVO.setDevices(devices);
            detailVO.setTotalUsageAmount(totalUsageAmount);

            // 设置状态中文描述
            detailVO.setStatusText(getStatusText(bill.getStatus()));
            detailVO.setInvoicedText(getInvoicedText(bill.getInvoiced()));

            return detailVO;
        } catch (Exception e) {
            log.error("获取账单详情失败，账单ID：{}", billId, e);
            throw new WaterException("获取账单详情失败: " + e.getMessage());
        }
    }

    @Override
    public BillDetailVO getBillDetailByCode(String billCode) {
        try {
            // 1. 根据账单编号查询账单
            Bill bill = findByBillCode(billCode);
            if (bill == null) {
                return null;
            }

            // 2. 调用根据ID查询详情的方法
            return getBillDetailById(bill.getId());
        } catch (Exception e) {
            log.error("根据账单编号获取账单详情失败，账单编号：{}", billCode, e);
            throw new WaterException("获取账单详情失败: " + e.getMessage());
        }
    }

    /**
     * 获取账单状态的中文描述
     */
    private String getStatusText(String status) {
        if (status == null) return "未知";
        switch (status) {
            case "unpaid": return "未支付";
            case "paid": return "已支付";
            case "overdue": return "逾期";
            case "refunded": return "已退款";
            default: return "未知";
        }
    }

    /**
     * 获取开票状态的中文描述
     */
    private String getInvoicedText(Integer invoiced) {
        if (invoiced == null) return "未知";
        return invoiced == 1 ? "已开票" : "未开票";
    }

    /**
     * 从设备数据表获取上次读数
     */
    private BigDecimal getLastReadingFromDeviceData(Long deviceId, String billingPeriod) {
        try {
            // 解析计费周期，获取上个月的数据
            String[] parts = billingPeriod.split("-");
            if (parts.length != 2) {
                throw new WaterException("计费周期格式错误: " + billingPeriod);
            }

            int year = Integer.parseInt(parts[0]);
            int month = Integer.parseInt(parts[1]);

            // 计算上个月
            if (month == 1) {
                month = 12;
                year--;
            } else {
                month--;
            }

            String lastMonth = String.format("%04d-%02d", year, month);

            // 查询上个月的数据
            LambdaQueryWrapper<DeviceData> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DeviceData::getDeviceId, deviceId)
                    .eq(DeviceData::getReadingDate, lastMonth + "-01"); // 使用月初作为查询条件

            DeviceData lastData = deviceDataMapper.selectOne(wrapper);

            if (lastData != null) {
                return lastData.getValue();
            }

            // 如果上个月没有数据，返回0
            return BigDecimal.ZERO;
        } catch (Exception e) {
            log.error("获取设备 {} 的上次读数失败: {}", deviceId, e.getMessage());
            return BigDecimal.ZERO;
        }
    }
}